home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / cmds / pmake / prefix / mount.c < prev    next >
Encoding:
C/C++ Source or Header  |  1989-11-15  |  17.4 KB  |  603 lines

  1. /***********************************************************************
  2.  *
  3.  * PROJECT:      PMake
  4.  * MODULE:      Prefix -- Mounting Routines
  5.  * FILE:      mount.c
  6.  *
  7.  * AUTHOR:        Adam de Boor: Jul  5, 1989
  8.  *
  9.  * ROUTINES:
  10.  *    Name              Description
  11.  *    ----              -----------
  12.  *    Mount_Init          Initialize the module
  13.  *    Mount_Unmount        Unmount an individual prefix.
  14.  *
  15.  * REVISION HISTORY:
  16.  *    Date      Name        Description
  17.  *    ----      ----        -----------
  18.  *    7/ 5/89      ardeb        Initial version
  19.  *
  20.  * DESCRIPTION:
  21.  *    Functions to deal with mounting a prefix
  22.  *
  23.  *     Copyright (c) Berkeley Softworks 1989
  24.  *     Copyright (c) Adam de Boor 1989
  25.  *
  26.  *     Permission to use, copy, modify, and distribute this
  27.  *     software and its documentation for any non-commercial purpose
  28.  *    and without fee is hereby granted, provided that the above copyright
  29.  *     notice appears in all copies.  Neither Berkeley Softworks nor
  30.  *     Adam de Boor makes any representations about the suitability of this
  31.  *     software for any purpose.  It is provided "as is" without
  32.  *     express or implied warranty.
  33.  *
  34.  ***********************************************************************/
  35. #ifndef lint
  36. static char *rcsid =
  37. "$Id: mount.c,v 1.9 89/10/10 00:35:50 adam Exp $";
  38. #endif lint
  39.  
  40. #include    "prefix.h"
  41. #include    "rpc.h"
  42. #include    "sunrpc.h"
  43.  
  44. static int              mountSock;  /* Socket over which NFS requests for
  45.                      * MOUNT_DIR arrive */
  46.  
  47. static struct nfsfattr  mattr;         /* Statistics for the mount directory */
  48.  
  49. /***********************************************************************
  50.  *                Mount_Unmount
  51.  ***********************************************************************
  52.  * SYNOPSIS:        Attempt to unmount a single prefix
  53.  *            THE PREFIX SHOULD HAVE BEEN CHECKED FOR LOCKS BEFORE
  54.  *            CALLING THIS PROCEDURE.
  55.  * CALLED BY:        ImportDelete, MountUnmountPrefix
  56.  * RETURN:        0 if failed
  57.  * SIDE EFFECTS:    The node is shifted onto the prefixes list if
  58.  *                unmounted.
  59.  *                The serverName and remote fields are freed and
  60.  *                NULLed.
  61.  *                The unmount event is deleted and the field zeroed.
  62.  *
  63.  * STRATEGY:
  64.  *
  65.  * REVISION HISTORY:
  66.  *    Name    Date        Description
  67.  *    ----    ----        -----------
  68.  *    ardeb    7/ 8/89        Initial Revision
  69.  *
  70.  ***********************************************************************/
  71. int
  72. Mount_Unmount(pp, answerPtr)
  73.     Prefix      *pp;            /* Prefix to unmount */
  74.     char        **answerPtr;    /* Place to store failure message */
  75. {
  76.     if (Child_Call(pp, PREFIX_UNMOUNT)) {
  77.     pp->flags &= ~PREFIX_MOUNTED;
  78.  
  79.     /*
  80.      * Nuke server data.
  81.      */
  82.     free(pp->serverName);
  83.     free(pp->remote);
  84.     pp->serverName = pp->remote = (char *)NULL;
  85.  
  86.     /*
  87.      * Delete the event for unmounting it...
  88.      */
  89.     if (pp->unmount) {
  90.         Rpc_EventDelete(pp->unmount);
  91.         pp->unmount = (Rpc_Event)NULL;
  92.     }
  93.     /*
  94.      * Announce our success
  95.      */
  96.     return(1);
  97.     } else {
  98.     *answerPtr = "prefix busy";
  99.     return(0);
  100.     }
  101. }
  102.  
  103.  
  104. /***********************************************************************
  105.  *                MountUnmountPrefix
  106.  ***********************************************************************
  107.  * SYNOPSIS:        Attempt to remove a prefix.
  108.  * CALLED BY:        Rpc event
  109.  * RETURN:        FALSE (no need to stay awake)
  110.  * SIDE EFFECTS:    If the prefix is unmounted it is either moved
  111.  *                back to the prefixes list and the mount point
  112.  *                taken over or, if the prefix is labeled as
  113.  *                temporary, the prefix is freed.
  114.  *
  115.  * STRATEGY:
  116.  *
  117.  * REVISION HISTORY:
  118.  *    Name    Date        Description
  119.  *    ----    ----        -----------
  120.  *    ardeb    7/ 6/89        Initial Revision
  121.  *
  122.  ***********************************************************************/
  123. static int
  124. MountUnmountPrefix(pp, ev)
  125.     Prefix      *pp;        /* Prefix to attempt to unmount */
  126.     Rpc_Event    ev;         /* Event that caused us to be called */
  127. {
  128.     char        *reason;
  129.  
  130.     dprintf("unmount(%s)...", pp->path);
  131.  
  132.     if (PrefixIsLocked(pp)) {
  133.     dprintf("locked\n");
  134.     } else if (!Mount_Unmount(pp, &reason)) {
  135.     /*
  136.      * Still active -- leave it alone until the next interval
  137.      * expires.
  138.      */
  139.     dprintf("%s\n", reason);
  140.     } else if ((pp->flags & PREFIX_TEMP) == 0) {
  141.     /*
  142.      * Permanent prefix -- remount it on ourselves.
  143.      */
  144.     dprintf("successful: remounting prefix\n");
  145.     Import_MountPrefix(pp);
  146.     } else {
  147.     dprintf("successful\n");
  148.     }
  149. }
  150.         
  151.  
  152.  
  153. /***********************************************************************
  154.  *                MountNullReq
  155.  ***********************************************************************
  156.  * SYNOPSIS:        Let the caller know we're alive
  157.  * CALLED BY:        RFS_NULL
  158.  * RETURN:        SUNRPC_SUCCESS
  159.  * SIDE EFFECTS:    None
  160.  *
  161.  * STRATEGY:
  162.  *
  163.  * REVISION HISTORY:
  164.  *    Name    Date        Description
  165.  *    ----    ----        -----------
  166.  *    ardeb    9/10/89        Initial Revision
  167.  *
  168.  ***********************************************************************/
  169. static enum clnt_stat
  170. MountNullReq(remote, msg, args, res, data, resPtr)
  171.     struct sockaddr_in    *remote;        /* Source of request */
  172.     Rpc_Message            msg;            /* Message token */
  173.     void            *args;            /* Arguments passed */
  174.     void            *res;            /* Results to return */
  175.     Rpc_Opaque            data;            /* Data we stored (UNUSED) */
  176.     void                **resPtr;       /* Room for modified 'res' (UNUSED)*/
  177. {
  178.     return(SUNRPC_SUCCESS);
  179. }
  180.  
  181. /***********************************************************************
  182.  *                MountGetAttrReq
  183.  ***********************************************************************
  184.  * SYNOPSIS:        Handle a GETATTR either on an entry we were given
  185.  *                by ImportReadLinkReq, or on the root of the
  186.  *                system itself.
  187.  * CALLED BY:        SunRpc
  188.  * RETURN:        SUNRPC_SUCCESS
  189.  * SIDE EFFECTS:    None.
  190.  *
  191.  * STRATEGY:
  192.  *
  193.  * REVISION HISTORY:
  194.  *    Name    Date        Description
  195.  *    ----    ----        -----------
  196.  *    ardeb    9/10/89        Initial Revision
  197.  *
  198.  ***********************************************************************/
  199. static enum clnt_stat
  200. MountGetAttrReq(remote, msg, args, res, data, resPtr)
  201.     struct sockaddr_in    *remote;        /* Source of request */
  202.     Rpc_Message            msg;            /* Message token */
  203.     PrefixHandle        *args;            /* Arguments passed */
  204.     struct nfsattrstat    *res;            /* Results to return */
  205.     Rpc_Opaque            data;            /* Data we stored (UNUSED) */
  206.     void                **resPtr;       /* Room for modified 'res' (UNUSED)*/
  207. {
  208.     Prefix              *pp;
  209.  
  210.     if (args->type == PH_SPECIAL) {
  211.     /*
  212.      * Need to tell the kernel this thing's a directory...
  213.      */
  214.     dprintf("GETATTR(%s)\n", MOUNT_DIR);
  215.     
  216.     res->ns_status         = NFS_OK;
  217.     res->ns_attr        = mattr;
  218.     } else {
  219.     pp = HandleToPrefix((fhandle_t *)args);
  220.     
  221.     if (pp == PREFIX_STALE) {
  222.         res->ns_status = NFSERR_STALE;
  223.     } else {
  224.         dprintf("MGETATTR(%s)\n", pp->path);
  225.     
  226.         res->ns_status = NFS_OK;
  227.         /*
  228.          * In this "directory", any other file is a symbolic
  229.          * link back to its real prefix.
  230.          */
  231.         res->ns_attr = link_attr;
  232.         res->ns_attr.na_size = strlen(pp->path);
  233.         res->ns_attr.na_blocksize = pp->attr.na_blocksize;
  234.     }
  235.     }
  236.     return(SUNRPC_SUCCESS);
  237. }
  238.  
  239. /***********************************************************************
  240.  *                MountReadLinkReq
  241.  ***********************************************************************
  242.  * SYNOPSIS:        Read one of our "symbolic links" -- this is our
  243.  *                signal to actually mount a prefix.
  244.  * CALLED BY:        SunRpc
  245.  * RETURN:        SUNRPC_SUCCESS if prefix mounted, SUNRPC_SYSTEMERR
  246.  *                if not.
  247.  * SIDE EFFECTS:    prefix is mounted.
  248.  *
  249.  * STRATEGY:
  250.  *
  251.  * REVISION HISTORY:
  252.  *    Name    Date        Description
  253.  *    ----    ----        -----------
  254.  *    ardeb    9/10/89        Initial Revision
  255.  *
  256.  ***********************************************************************/
  257. static enum clnt_stat
  258. MountReadLinkReq(remote, msg, args, res, data, resPtr)
  259.     struct sockaddr_in    *remote;        /* Source of request */
  260.     Rpc_Message            msg;            /* Message token */
  261.     fhandle_t            *args;            /* Arguments passed */
  262.     struct nfsrdlnres    *res;            /* Results to return */
  263.     Rpc_Opaque            data;            /* Data we stored (UNUSED) */
  264.     void                **resPtr;       /* Room for modified 'res' (UNUSED)*/
  265. {
  266.     Prefix              *pp;
  267.     LstNode            ln;
  268.     struct sockaddr_in  sin;
  269.     struct timeval    retry;
  270.     
  271.     pp = HandleToPrefix(args);
  272.  
  273.     dprintf("MREADLINK: ");
  274.     if (pp == PREFIX_STALE) {
  275.     dprintf("STALE\n");
  276.     res->rl_status = NFSERR_STALE;
  277.     } else if (PrefixIsLocked(pp)) {
  278.     /*
  279.      * If prefix is in flux, we don't want to try and mount it -- just
  280.      * drop the request on the floor. Hopefully, when the kernel
  281.      * retransmits its request the prefix will be stable again.
  282.      *
  283.      * Note that we can't just hang out here, as then the pending
  284.      * request that we interrupted in an earlier frame won't be returned
  285.      * to...
  286.      */
  287.     dprintf("LOCKED\n");
  288.     return(SUNRPC_DONTRESPOND);
  289.     } else if (pp->serverName == NULL) {
  290.     /*
  291.      * Couldn't find the server -- pretend there's nothing
  292.      * here.
  293.      */
  294.     dprintf("server for '%s' unknown\n", pp->path);
  295.     res->rl_status = NFSERR_NOENT;
  296.     } else if (pp != NULL) {
  297.     dprintf("MREADLINK(%s)\n", pp->path);
  298.     
  299.     res->rl_status = NFS_OK;
  300.     
  301.     if ((pp->flags & PREFIX_MOUNTED) == 0) {
  302.         /*
  303.          * Unmount our prefix and mount the real one.
  304.          * Note that Child_Call takes care of any necessary locks on
  305.          * the prefix.
  306.          */
  307.         struct timeval    unmountTime;
  308.         
  309.         if (pp->flags & PREFIX_TEMP) {
  310.         dprintf("%s: nothing to unmount\n", pp->path);
  311.         } else {
  312.         dprintf("unmount %s...", pp->path);
  313.         if (!Child_Call(pp, PREFIX_UNMOUNT_LOCAL)) {
  314.             return(RPC_SYSTEMERROR);
  315.         }
  316.         dprintf("successful\n");
  317.         }
  318.         dprintf("mount %s from %s...", pp->remote, pp->serverName);
  319.         
  320.         if (!Child_Call(pp, PREFIX_MOUNT)) {
  321.         /*
  322.          * Re-mount ourselves, if necessary, so the
  323.          * user can try again later.
  324.          */
  325.         if ((pp->flags & PREFIX_TEMP) == 0) {
  326.             Import_MountPrefix(pp);
  327.         }
  328.         return (RPC_SYSTEMERROR);
  329.         } else {
  330.         pp->flags |= PREFIX_MOUNTED;
  331.         }
  332.         
  333.         dprintf("successful\n");
  334.         
  335.         /*
  336.          * Create event for unmounting this prefix.
  337.          */
  338.         unmountTime.tv_sec = UNMOUNT_INTERVAL;
  339.         unmountTime.tv_usec = 0;
  340.         
  341.         pp->unmount = Rpc_EventCreate(&unmountTime,
  342.                       MountUnmountPrefix,
  343.                       (Rpc_Opaque)pp);
  344.     } else {
  345.         dprintf("already mounted\n");
  346.     }
  347.     
  348.     /*
  349.      * Return a symbolic link back to the prefix...
  350.      * Sets up return value at the end of the nfsrdlnres
  351.      */
  352.     res->rl_count = strlen(pp->path);
  353.     res = (struct nfsrdlnres *)realloc(res, sizeof(*res)+res->rl_count);
  354.     *resPtr = (void *)res;
  355.     res->rl_data = (char *)(res+1);
  356.     bcopy(pp->path, res->rl_data, res->rl_count);
  357.     } else {
  358.     dprintf("pp == NULL\n");
  359.     res->rl_status = NFSERR_NOENT;
  360.     }
  361.  
  362.     return(SUNRPC_SUCCESS);
  363. }
  364.     
  365.  
  366. /***********************************************************************
  367.  *                MountStatFSReq
  368.  ***********************************************************************
  369.  * SYNOPSIS:        Another bogus STATFS handler, since this filesystem
  370.  *                doesn't exist either
  371.  * CALLED BY:        SunRpc for RFS_STATFS
  372.  * RETURN:        SUNRPC_SUCCESS
  373.  * SIDE EFFECTS:    None
  374.  *
  375.  * STRATEGY:
  376.  *
  377.  * REVISION HISTORY:
  378.  *    Name    Date        Description
  379.  *    ----    ----        -----------
  380.  *    ardeb    9/10/89        Initial Revision
  381.  *
  382.  ***********************************************************************/
  383. static enum clnt_stat
  384. MountStatFSReq(remote, msg, args, res, data, resPtr)
  385.     struct sockaddr_in    *remote;        /* Source of request */
  386.     Rpc_Message            msg;            /* Message token */
  387.     fhandle_t            *args;            /* Arguments passed */
  388.     struct nfsstatfs    *res;            /* Results to return */
  389.     Rpc_Opaque            data;            /* Data we stored (UNUSED) */
  390.     void                **resPtr;       /* Room for modified 'res' (UNUSED)*/
  391. {
  392.     dprintf("STATFS(%s)\n", MOUNT_DIR);
  393.     
  394.     bzero(res, sizeof(*res));
  395.     
  396.     /*
  397.      * Return bogus information for the filesystem for now
  398.      */
  399.     res->fs_status = NFS_OK;
  400.     res->fs_tsize = res->fs_bsize = 8192;
  401.     res->fs_blocks = 1;
  402.     res->fs_bfree = 0;
  403.     res->fs_bavail = 0;
  404.  
  405.     return(SUNRPC_SUCCESS);
  406. }
  407.  
  408. /***********************************************************************
  409.  *                MountLookupReq
  410.  ***********************************************************************
  411.  * SYNOPSIS:        Deal with a directory lookup in this filesystem
  412.  * CALLED BY:        SunRpc RFS_LOOKUP
  413.  * RETURN:        SUNRPC_SUCCESS
  414.  * SIDE EFFECTS:    None
  415.  *
  416.  * STRATEGY:
  417.  *
  418.  * REVISION HISTORY:
  419.  *    Name    Date        Description
  420.  *    ----    ----        -----------
  421.  *    ardeb    9/10/89        Initial Revision
  422.  *
  423.  ***********************************************************************/
  424. static enum clnt_stat
  425. MountLookupReq(remote, msg, args, res, data, resPtr)
  426.     struct sockaddr_in    *remote;        /* Source of request */
  427.     Rpc_Message            msg;            /* Message token */
  428.     struct nfsdiropargs    *args;            /* Arguments passed */
  429.     struct nfsdiropres    *res;            /* Results to return */
  430.     Rpc_Opaque            data;            /* Data we stored (UNUSED) */
  431.     void                **resPtr;       /* Room for modified 'res' (UNUSED)*/
  432. {
  433.     Prefix              *pp;
  434.     PrefixHandle        ph;
  435.  
  436.     /*
  437.      * The name consists of two integers separated by a decimal point.
  438.      * The first integer is the address of the Prefix involved, while the
  439.      * second is the generation number for the prefix. We need to scan
  440.      * them into a PrefixHandle structure for HandleToPrefix to use...
  441.      */
  442.     dprintf("MLOOKUP(%s)\n", args->da_name);
  443.     ph.rd.type = PH_REGULAR;
  444.     sscanf(args->da_name, "%d.%d", &ph.rd.pp, &ph.rd.generation);
  445.     pp = HandleToPrefix((fhandle_t *)&ph);
  446.     
  447.     if (pp == PREFIX_STALE) {
  448.     dprintf("\tSTALE HANDLE\n");
  449.     res->dr_status = NFSERR_STALE;
  450.     } else if (pp == NULL) {
  451.     dprintf("\tNO SUCH PREFIX\n");
  452.     res->dr_status = NFSERR_NOENT;
  453.     } else {
  454.     dprintf("\tMLOOKUP(%s)\n", pp->path);
  455.     res->dr_status = NFS_OK;
  456.     
  457.     /*
  458.      * Handle is same as always...
  459.      */
  460.     PrefixToHandle(pp, &res->dr_fhandle);
  461.     
  462.     /*
  463.      * All prefixes are symbolic links until they're mounted.
  464.      * (the thing can't be mounted or we wouldn't be here)
  465.      */
  466.     res->dr_attr = link_attr;
  467.     res->dr_attr.na_size        = strlen(pp->path);
  468.     res->dr_attr.na_blocksize    = pp->attr.na_blocksize;
  469.     }
  470.  
  471.     return(SUNRPC_SUCCESS);
  472. }
  473.         
  474.  
  475. /***********************************************************************
  476.  *                Mount_Init
  477.  ***********************************************************************
  478.  * SYNOPSIS:        Initialize things here
  479.  * CALLED BY:        main
  480.  * RETURN:        Nothing
  481.  * SIDE EFFECTS:    The mount directory is created and statted
  482.  *
  483.  * STRATEGY:
  484.  *
  485.  * REVISION HISTORY:
  486.  *    Name    Date        Description
  487.  *    ----    ----        -----------
  488.  *    ardeb    7/ 6/89        Initial Revision
  489.  *
  490.  ***********************************************************************/
  491. void
  492. Mount_Init()
  493. {
  494.     struct stat    stb;
  495.     
  496.     /*
  497.      * Make sure special directory is around
  498.      */
  499.     (void)mkdir(MOUNT_DIR, 0555);
  500.  
  501.     /*
  502.      * Fetch its attributes
  503.      */
  504.     if (stat(MOUNT_DIR, &stb) < 0) {
  505.     perror(MOUNT_DIR);
  506.     exit(1);
  507.     }
  508.  
  509.     /*
  510.      * Covert to NFS Normal Form
  511.      */
  512.     mattr.na_type            = NFDIR;
  513.     mattr.na_mode             = 0555 | S_IFDIR;
  514.     mattr.na_nlink            = 1;
  515.     mattr.na_uid        = stb.st_uid;
  516.     mattr.na_gid        = stb.st_gid;
  517.     mattr.na_size        = stb.st_size;
  518.     mattr.na_blocksize        = stb.st_blksize;
  519.     mattr.na_rdev        = -1;
  520.     mattr.na_blocks        = stb.st_blocks;
  521.     mattr.na_fsid        = -1;
  522.     mattr.na_nodeid        = stb.st_ino;
  523.     mattr.na_atime.tv_sec   = stb.st_atime;
  524.     mattr.na_atime.tv_usec  = stb.st_spare1;
  525.     mattr.na_mtime.tv_sec   = stb.st_mtime;
  526.     mattr.na_mtime.tv_usec  = stb.st_spare2;
  527.     mattr.na_ctime.tv_sec   = stb.st_ctime;
  528.     mattr.na_ctime.tv_usec  = stb.st_spare3;
  529.  
  530.     /*
  531.      * Create a socket for ourselves -- it can be anywhere in the UDP
  532.      * address space.
  533.      */
  534.     mountSock = Rpc_UdpCreate(True, 0);
  535.  
  536.     /*
  537.      * Register the Sun RPC servers for the socket. These are the only
  538.      * NFS procedures we handle -- anything else generates a "procedure
  539.      * unavailable" error.
  540.      */
  541.     SunRpc_ServerCreate(mountSock, NFS_PROGRAM, RFS_NULL, NFS_VERSION,
  542.             MountNullReq, (Rpc_Opaque)NULL,
  543.             0, xdr_void, 0, xdr_void);
  544.  
  545.     SunRpc_ServerCreate(mountSock, NFS_PROGRAM, RFS_GETATTR, NFS_VERSION,
  546.             MountGetAttrReq, (Rpc_Opaque)NULL,
  547.             sizeof(fhandle_t), xdr_fhandle,
  548.             sizeof(struct nfsattrstat), xdr_attrstat);
  549.  
  550.     SunRpc_ServerCreate(mountSock, NFS_PROGRAM, RFS_READLINK, NFS_VERSION,
  551.             MountReadLinkReq, (Rpc_Opaque)NULL,
  552.             sizeof(fhandle_t), xdr_fhandle,
  553.             sizeof(struct nfsrdlnres), xdr_rdlnres);
  554.  
  555.     SunRpc_ServerCreate(mountSock, NFS_PROGRAM, RFS_LOOKUP, NFS_VERSION,
  556.             MountLookupReq, (Rpc_Opaque)NULL,
  557.             sizeof(struct nfsdiropargs), xdr_diropargs,
  558.             sizeof(struct nfsdiropres), xdr_diropres);
  559.  
  560.     SunRpc_ServerCreate(mountSock, NFS_PROGRAM, RFS_STATFS, NFS_VERSION,
  561.             MountStatFSReq, (Rpc_Opaque)NULL,
  562.             sizeof(fhandle_t), xdr_fhandle,
  563.             sizeof(struct nfsstatfs), xdr_statfs);
  564.  
  565. }
  566.  
  567.  
  568. /***********************************************************************
  569.  *                Mount_MountRoot
  570.  ***********************************************************************
  571.  * SYNOPSIS:        Use our child process to mount ourselves on MOUNT_DIR
  572.  * CALLED BY:        main
  573.  * RETURN:        True if successful.
  574.  * SIDE EFFECTS:    >?
  575.  *
  576.  * STRATEGY:
  577.  *
  578.  * REVISION HISTORY:
  579.  *    Name    Date        Description
  580.  *    ----    ----        -----------
  581.  *    ardeb    9/10/89        Initial Revision
  582.  *
  583.  ***********************************************************************/
  584. int
  585. Mount_MountRoot()
  586. {
  587.     struct sockaddr_in    sin;
  588.     int                    addrlen = sizeof(sin);
  589.  
  590.     /*
  591.      * Need to locate the port for the socket so Child_MountSpecial can
  592.      * tell the kernel where we are.
  593.      */
  594.     if (getsockname(mountSock, &sin, &addrlen) < 0) {
  595.     return(False);
  596.     }
  597.  
  598.     /*
  599.      * Now tell the child to mount us on MOUNT_DIR.
  600.      */
  601.     return(Child_MountSpecial(sin.sin_port, MOUNT_DIR));
  602. }
  603.